<?php

declare(strict_types=1);

namespace App\Kernel\Util;

use App\Dao\UserDao;
use App\Exception\BusinessException;
use App\Model\User;
use Firebase\JWT\JWT;
use Hyperf\Utils\Traits\StaticInstance;

class JwtInstance
{
    use StaticInstance;

    const KEY = 'Hyperf-admin';

    /**
     * @var int
     */
    public $user_id;

    /**
     * @var User
     */
    public $user;

    public function encode(User $sysUser)
    {
        $this->user_id = $sysUser->id;
        $this->user = $sysUser;

        return JWT::encode([
            'iss' => 'xxx.com', //签发者 可选
            'iat' => time(), //签发时间
            'exp' => time() + config("sys_token_exp"),
            'id' => $sysUser->id
        ], self::KEY);
    }

    public function decode(string $token): self
    {

        try {
            $decoded = (array)JWT::decode($token, self::KEY, ['HS256']);
        } catch (\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
            throw new BusinessException($e->getMessage());
        } catch (\Firebase\JWT\ExpiredException $e) {  // token过期
            throw new BusinessException($e->getMessage());
        } catch (\Throwable $e) {
            throw new BusinessException($e->getMessage());
        }

        if ($id = $decoded['id'] ?? null) {
            $this->user_id = $id;
//            $this->user = UserDao::first($id);
        }
        return $this;
    }

    public function build(): self
    {
        if (empty($this->user_id)) {
            throw new BusinessException('ErrorCode::TOKEN_INVALID');
        }
        return $this;
    }

    /**
     * @return int
     */
    public function getId(): ?int
    {
        return $this->user_id;
    }

    /**
     * @return User
     */
    public function getUser(): ?User
    {
        if ($this->user === null && $this->user_id) {
            $this->user = di(UserDao::class)->first($this->user_id);
        }
        return $this->user;
    }
}
